
#ifndef __TABLAHASH_H__
#define __TABLAHASH_H__

#include "Bucket.h"

	typedef struct Buffer
	{
		int nroBloque;
		unsigned int * Buckets; // Lista de numeros de buckets, contenidos en el bloque de tabla particular
		enum TBOOL lru; //indica cual es el bloque menos recientemente usado
	}Buffer;

	typedef struct TablaHash
	{
		TamBucket tamanioBucket;
		unsigned int tamanioTabla;
		//unsigned int bloqueActual; // Nro de Bloque de la tabla actualmente levantado en memoria. NroBloque != NroBucket !!!
		Buffer * buffer; //Se tendran en memoria 2 bloques de tabla unicamente
		unsigned int cantBuckets; // Suma de la cantidad de Buckets utilizados y los Buckets libres. Se usa para asginarle el nroBucket a un Bucket nuevo.
	}TablaHash;

	/* Crea una tabla y la deja en un estado valido. */
	TablaHash* crearTabla();

	/* Devuelve el indice del bucket que contiene la clave en la Tabla segun su tamaño, funcion de hashing modular*/
	unsigned int IndiceEnTabla (TClave clave, unsigned int tamanioTabla);

	/*Devuelve el numero de Bloque que contiene el 'indiceTabla'. indiceTabla es el indice que contempla toda la tabla completa*/
	unsigned int getNroBloqueByIndiceTabla(unsigned int indiceTabla);

	/*Asigna la direccion de un bucket dentro de un rango del vector Buckets*/
	int GuardarBucketEnTabla (FILE* archTabla, TablaHash* tabla, unsigned int nroBucket, unsigned int dispersion, int indiceTabla);

	/*PRE: recibe la tabla, el valor del nuevo bloque creado y la posicion donde debe insertarse en la tabla*/
	int DuplicarTabla (FILE* archTabla, TablaHash* tabla);

	/* si ambas mitades de la tabla son iguales la trunca, si se elimino el ultimo bloque, la tabla queda vacia
	 * Actualiza el archivo de Tabla
	 * */
	int ReducirTabla (TablaHash* tabla, FILE * archTabla);

	/*Calcula la cantidad de bloques que se usan en el archivo de Tabla*/
	int getCantBloquesTabla (TablaHash tabla);

	/*Copia un bloque de la tabla en un vector de char para persistir*/
	void BloqueTablaABytes(TablaHash* tabla, char* bloqueAPersistir, int nroBloque);

	/*Copia datos de control a un vector de char para persistir la MetaData*/
	void MetaDataABytes(TablaHash* tabla, char* metadata);

	/*Guarda solo la MetaData en el archivo de Tabla, ocupando sólo los primeros 512 bytes*/
	int GuardarMetaData (FILE* archTabla, TablaHash* tabla);

	/*Levanta solo la MetaData del archivo de Tabla*/
	int LevantarMetaData (FILE* archTabla, TablaHash* tabla);

	/*Guarda uno de los bloques buffer (tabla->buffer) de la tabla segun 'indiceBuffer'*/
	int GuardarBloqueTabla (FILE* archTabla, TablaHash* tabla, int indiceBuffer);

	/*Levanta un bloque del archivo de la Tabla, dado 'nroBloque'
	 * PRE: Metadata en memoria*/
	int LevantarBloqueTabla (FILE* archTabla, TablaHash * tabla, unsigned int nroBloque);

	/*Asigna a tabla->buffer[indice] como recientemente usado, es decir FALSE*/
	void setIndiceBufferLRU (TablaHash * tabla, int indice);

	/*Devuelve el indice de tabla->buffer en el cual se encuentra 'nroBloque'. Si no esta en memoria
	 *  llama a LevantarBloqueTabla y devuelve el indice en el que se levanto el bloque de tabla*/
	int getIndiceBufferByNroBloque (FILE * archTabla, TablaHash * tabla, unsigned int nroBloque);

	/*Devuelve el indice de tabla->buffer de acuerdo al estado 'isLru' */
	int getIndiceBufferLRU (TablaHash * tabla, enum TBOOL isLru);

	/*muestra por 'salida' el estado de la tabla*/
	void visualizarTabla(FILE* archTabla, TablaHash* tabla, FILE* salida);


#endif /*__TABLAHASH_H__*/
